package com.chinawu.cloud.ss.config.sharding;

import com.google.common.collect.Range;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p class="detail">
 * 功能：单分片键范围分片算法 BETWEEN AND、>、<、>=、<=
 * </p>
 *
 * @author wuyubin
 * Copyright 2021 chinawu.com, Inc. All rights reserved
 * @version V1.0
 * @ClassName: RangeTimeShardingAlgorithm
 * @date 2021年07月28日 16:52
 */
public class RangeTimeShardingAlgorithm implements RangeShardingAlgorithm<Long> {

    private Logger LOGGER = LoggerFactory.getLogger(RangeTimeShardingAlgorithm.class);

    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Long> rangeShardingValue) {
        String logicTableName = rangeShardingValue.getLogicTableName();
        LOGGER.info("[单分片键范围分片算法]分片键：{} 逻辑表：{}",rangeShardingValue.getColumnName(),logicTableName);
        Range<Long> range = rangeShardingValue.getValueRange();
        LOGGER.info("范围区间range:{}",range.toString());
        for (String tbName : collection) {
            LOGGER.info("范围区间分库分表配置参数,{}",tbName);
        }

        List<String> shardingSuffix = new ArrayList<String>();

        shardingSuffix = checkTable(logicTableName,range.hasLowerBound()?range.lowerEndpoint():null,range.hasUpperBound()?range.upperEndpoint():null);
        for (String tableName : shardingSuffix) {
            System.out.println("tableName:"+tableName);
        }
        return shardingSuffix;
    }

    private List<String> checkTable(String logicTableName,Long startTime,Long endTime) {
        List<String> tables = new ArrayList<>();
        try {
            if (startTime != null && endTime != null) {
                tables = getMonthBetween(logicTableName,new Date(startTime),new Date(endTime));
            } else if (startTime != null && endTime == null) {
                tables = getMonthBetween(logicTableName,new Date(startTime),new Date());
            } else if (startTime == null && endTime != null) {
                tables = getMonthBetween(logicTableName,new Date(1591771874000L),new Date(endTime));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return tables;
    }

    public static List<String> getMonthBetween(String logicTableName,Date minDate, Date maxDate) throws Exception {
        ArrayList<String> result = new ArrayList<String>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");//格式化为年月

        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();

        min.setTime(minDate);
        min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);

        max.setTime(maxDate);
        max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);

        Calendar curr = min;
        while (curr.before(max)) {
            result.add(logicTableName+"_"+sdf.format(curr.getTime()));
            curr.add(Calendar.MONTH, 1);
        }

        return result;
    }

    public static void main(String[] args) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//格式化为年月
            List<String> list = getMonthBetween("t_order",sdf.parse("1999-05-01"),sdf.parse("2021-11-30"));
            for (String str : list) {
                System.out.println("str:"+str);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
